﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using T0yK4T.IO;
using ToyChat.Server;

namespace ToyChat.Core
{
    public class Core : IModule
    {
        #region Type Definitions
        /// <summary>
        /// This type is used for UserInfo messages
        /// </summary>
        public const string TYPE_USERINFO = "Core.UserInfo";

        /// <summary>
        /// This type is used for UserJoined messages
        /// </summary>
        public const string TYPE_USERJOIN = "Core.UserJoined";

        /// <summary>
        /// This type is used for UserLeft messages
        /// </summary>
        public const string TYPE_USERLEFT = "Core.UserLeft";

        /// <summary>
        /// This type is used for GetPermissions messages
        /// </summary>
        public const string TYPE_GETPERMS = "Core.GetPermissions";

        /// <summary>
        /// This type is used to <see cref="UserPermissions"/> messages
        /// </summary>
        public const string TYPE_USERPERMS = "Core.UserPermissions";

        /// <summary>
        /// This type is used for the "initial" channel informations sent by the server to the client when the client first joins a channel
        /// </summary>
        public const string TYPE_CINFOMSG = "Core.ChannelInfo";

        /// <summary>
        /// This type is used for basic messages
        /// </summary>
        public const string TYPE_MESSAGE = "Core.BasicMessage";

        /// <summary>
        /// This type is used for <see cref="UserDisconnectedMessage"/>s
        /// </summary>
        public const string TYPE_USERDC = "Core.UserDisconnected";

        /// <summary>
        /// This type is used for <see cref="ServerInfoMessage"/>s
        /// </summary>
        public const string TYPE_SERVERINFO = "Core.ServerInfo";

        /// <summary>
        /// This type is used for <see cref="ChannelList"/> messages
        /// </summary>
        public const string TYPE_CHANNELLIST = "Core.ChannelList";

        /// <summary>
        /// This type is used for <see cref="ChannelControlMessage"/>s
        /// </summary>
        public const string TYPE_CHANNELCTRL = "Core.ChannelControlMessage";

        private static readonly string[] types = new string[]
        {
            TYPE_USERINFO,
            TYPE_USERJOIN,
            TYPE_USERLEFT,
            TYPE_GETPERMS,
            TYPE_USERPERMS,
            TYPE_CINFOMSG,
            TYPE_MESSAGE,
            TYPE_SERVERINFO,
            TYPE_CHANNELLIST,
            TYPE_CHANNELCTRL,
            TYPE_USERDC,
        };

        #endregion Type Definitions

        private Dictionary<uint, ICoreModule> internalSwitch = new Dictionary<uint, ICoreModule>();
        private IServer server;
        private IClient client;
        private Dictionary<uint, IUser> discoveredUsers = new Dictionary<uint, IUser>();

        public Core()
        {

        }

        #region IModule Members

        public void Initialize(IClient component)
        {
            throw new NotImplementedException();
        }

        public void Initialize(IServer component)
        {
            throw new NotImplementedException();
        }

        public void OnPacket(Packet packet)
        {
            if (this.server != null)
                this.OnPacket(packet, this.GetSourceUser_Server(packet));
            else if (this.client != null) { }
        }

        private IUser GetSourceUser_Server(Packet packet)
        {
            IUser res = null;
            if (this.server != null)
                this.server.UserHandler.TryGetUser(packet.SourceUserID, out res);
            return res;
        }

        private void OnPacket(Packet packet, IUser user)
        {
            ICoreModule handler;
            if (this.internalSwitch.TryGetValue(packet.TypeID, out handler))
                handler.OnPacket(packet, user);
        }

        public string[] Types
        {
            get { return types; }
        }

        public void SetTypeID(string type, uint id)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}
